import VueRouter from 'vue-router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import storage from '@/utils/storage.js'
import store from '@/store/index.js'
import { getGenerateTitle } from '@/utils/i18n.js'
import { ACCESS_TOKEN } from '@/store/mutationTypes.js'
import { isFunction } from '@/utils/is.js'

const { isNavigationFailure } = VueRouter

const DEFAULT_ROUTE_PATH = '/dashboard'
const LOGIN_ROUTE_PATH = '/login'

// 免登录白名单
const whiteList = ['login', 'error', 'error-404', '404']

// 通过设置false来关闭加载旋转器(默认是显示的)
NProgress.configure({ showSpinner: false })

/**
* @description 有token的处理函数--私有函数
* @param { router } router
* @param { to } to
* @param { from } from
* @param { next } next
*/
async function hasLogin({ router, to, from, next }) {
  if (to.name && to.name === 'login') {
    next({ path: DEFAULT_ROUTE_PATH })
    NProgress.done()
  } else {
    const hasRoles = store.getters['user/roles'] && store.getters['user/roles'].length > 0
    if (hasRoles) {
      next()
    } else {
      const userInfo = store.getters['user/userInfo']
      if (Object.prototype.hasOwnProperty.call(userInfo, 'role')) {
        const { role } = userInfo
        store.commit('user/setRoles', [role])
        // 动态获取异步路由--从而进行角色权限路由设置
        const accessRoutes = await store.dispatch('asyncRoute/generateRoutes', [role])
        // 动态加入路由列表--vue-router3.2.0版本之后废除了addRoutes方法，改用addRoute
        router.addRoutes(accessRoutes)
      }
      next({ ...to, replace: true })
    }
  }
}

/**
* @description 无token的处理函数--私有函数
* @param { router } router
* @param { to } to
* @param { from } from
* @param { next } next
*/
function hasNoLogin({ router, to, from, next }) {
  if (to.name && whiteList.includes(to.name)) {
    // 白名单中，免登录直接进入
    next()
  } else {
    // 非白名单路由--跳转拦截跳转登录页面
    next({ path: `${LOGIN_ROUTE_PATH}?redirect=${to.path}`, replace: true })
    NProgress.done()
  }
}

/**
* @description 路由守卫方法
* @param {router} router
*/
export function createRouterGuards(router) {
  // 全局前置守卫
  router.beforeEach((to, from, next) => {
    NProgress.start()
    // 获取缓存中的token
    const token = storage.get(ACCESS_TOKEN)
    if (token) {
      hasLogin({ router, to, from, next })
    } else {
      hasNoLogin({ router, to, from, next })
    }
  })

  // 全局后置守卫
  router.afterEach((to, from, failure) => {
    document.title = getGenerateTitle(to.meta && to.meta.title ? to.meta.title : document.title)
    // 导航故障
    if (isFunction(isNavigationFailure) && isNavigationFailure(failure)) {
      console.log('路由导航故障', failure)
    }

    // TODO:设置需要缓存的组件名称
    const keepAliveComponents = store.state.asyncRoute.keepAliveComponents
    const currentComponent = to.matched.find(item => item.name === to.name)
    if (currentComponent) {
      const currentComponentName = currentComponent.components.default.name
      if (currentComponentName && !keepAliveComponents.includes(currentComponentName) && to.meta && to.meta.keepAlive) {
        // 加入缓存数组中
        keepAliveComponents.push(currentComponentName)
      }
    }
    // console.log(currentComponent)
    store.commit('asyncRoute/setKeepAliveComponents', keepAliveComponents)
    NProgress.done()
  })
  // 路由出错
  router.onError((e) => {
    console.log('路由出错', e)
  })
}
